package com.qiqi.ctbluetooth

import android.bluetooth.BluetoothGatt
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import com.blankj.utilcode.util.LogUtils
import com.clj.fastble.BleManager
import com.clj.fastble.callback.BleGattCallback
import com.clj.fastble.callback.BleMtuChangedCallback
import com.clj.fastble.callback.BleNotifyCallback
import com.clj.fastble.callback.BleScanCallback
import com.clj.fastble.callback.BleWriteCallback
import com.clj.fastble.data.BleDevice
import com.clj.fastble.exception.BleException
import com.clj.fastble.scan.BleScanRuleConfig
import com.clj.fastble.utils.HexUtil
import com.kongzue.dialogx.dialogs.PopTip
import com.kongzue.dialogx.dialogs.WaitDialog
import com.qiqi.ctbluetooth.data.BlueDeviceData
import com.qiqi.ctbluetooth.util.Constant
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.asStateFlow
import kotlinx.coroutines.launch
import java.io.ByteArrayOutputStream
import java.util.UUID

class BlueViewModel: ViewModel() {
    // 设备列表
    private val _bleDeviceList = MutableStateFlow<MutableList<BlueDeviceData>>(mutableListOf())
    val bleDeviceList: StateFlow<MutableList<BlueDeviceData>> = _bleDeviceList.asStateFlow()

    // 连接的设备
    private val _connectDevice = MutableStateFlow<BleDevice?>(null)
    val connectDevice: StateFlow<BleDevice?> = _connectDevice.asStateFlow()

    // 蓝牙操作回调
    var onScanStarted: (() -> Unit)? = null
    var onScanFinished: (() -> Unit)? = null
    var onDeviceFound: ((BleDevice) -> Unit)? = null

    var onConnectSuccess: ((BleDevice) -> Unit)? = null
    var onConnectFailed: ((BleDevice, BleException) -> Unit)? = null
    var onDisconnected: ((BleDevice) -> Unit)? = null
    var onCompleteData: ((ByteArray) -> Unit)? = null


    // 添加缓冲池相关变量
    private val receiveBuffer = ByteArrayOutputStream()


    /**
     * 开始扫描蓝牙设备
     */
    fun startScanBlue() {
        viewModelScope.launch {
            _bleDeviceList.value = mutableListOf()

            BleManager.getInstance().initScanRule(
                BleScanRuleConfig.Builder()
                    .setServiceUuids(arrayOf(UUID.fromString(Constant.BLUE_SERVICE_UUID)))
                    .setScanTimeOut(10000)
                    .build()
            )

            BleManager.getInstance().scan(object : BleScanCallback() {
                override fun onScanFinished(list: List<BleDevice>) {
                    LogUtils.e("扫描结束")
                    onScanFinished?.invoke()
                }

                override fun onScanStarted(boolean: Boolean) {
                    onScanStarted?.invoke()
                }

                override fun onScanning(device: BleDevice) {
                    val currentList = _bleDeviceList.value.toMutableList()
                    if (!currentList.any { it.device.mac == device.mac }) {
                        currentList.add(BlueDeviceData(checked = false, device = device))
                        _bleDeviceList.value = currentList
                    }
                    onDeviceFound?.invoke(device)
                }
            })
        }
    }

    fun connectBleDevice(device: BleDevice){
        BleManager.getInstance().cancelScan()
        BleManager.getInstance().connect(device, object : BleGattCallback() {
            override fun onStartConnect() {
                LogUtils.e("-----onStartConnect")
                WaitDialog.show("正在连接...")
            }

            override fun onConnectFail(bleDevice: BleDevice, exception: BleException) {
                LogUtils.e("-----onConnectFail ===》 bleDevice ==》${bleDevice} exception ==》${exception}")
                onConnectFailed?.invoke(bleDevice, exception)
            }

            override fun onConnectSuccess(bleDevice: BleDevice, gatt: BluetoothGatt, status: Int) {
                _connectDevice.value = bleDevice
                onConnectSuccess?.invoke(bleDevice)

                setBlueMtu(bleDevice,512)

                // 延迟1秒后再设置通知
                viewModelScope.launch {
                    kotlinx.coroutines.delay(500)
                    setBlueNotify(bleDevice)
                }
                UserDataLocal.addConnectDevice(device.mac)
            }

            override fun onDisConnected(
                isActiveDisConnected: Boolean,
                bleDevice: BleDevice,
                gatt: BluetoothGatt,
                status: Int
            ) {
                LogUtils.e("-----${bleDevice.name} -> onDisConnected: $isActiveDisConnected")
                _connectDevice.value = null
                onDisconnected?.invoke(bleDevice)
            }
        })
    }
    /**
     * 设置最大传输单元MTU
     */
    fun setBlueMtu(bleDevice: BleDevice, mtu: Int) {
        BleManager.getInstance().setMtu(bleDevice, mtu, object : BleMtuChangedCallback() {
            override fun onSetMTUFailure(p0: BleException?) {
                // 设置MTU失败
                LogUtils.e("-----${bleDevice.name} -> 设置设置MTU失败")
            }

            override fun onMtuChanged(num: Int) {
                // 设置MTU成功，并获得当前设备传输支持的MTU值
                LogUtils.e("-----${bleDevice.name} -> 设置设置MTU成功,当前设备传输支持的MTU值：$num")
            }

        });
    }

    fun setBlueNotify(bleDevice: BleDevice){
        BleManager.getInstance().notify(
            bleDevice,
            Constant.BLUE_SERVICE_UUID,
            Constant.BLUE_READ_UUID,
            object : BleNotifyCallback() {
                override fun onNotifySuccess() {
                    LogUtils.iTag("notify", "notify成功：${Constant.BLUE_READ_UUID}")
                    sendData(UserDataLocal.sendData)
                }

                override fun onNotifyFailure(t: BleException) {
                    PopTip.show("设置蓝牙通知失败")
                    LogUtils.iTag("notify", "notify失败：${t}")
                }

                override fun onCharacteristicChanged(data: ByteArray) {
                    // 处理缓冲池数据
                    processDataWithBuffer(data)

                }
            }
        )
    }

    /**
     * 使用缓冲池处理接收到的数据
     */
    private fun processDataWithBuffer(data: ByteArray) {
        for (byte in data) {
            // 将当前字节添加到缓冲池中
            receiveBuffer.write(byte.toInt())

            // 当前字节为0xff时，检查并处理之前累积的数据
            if (byte == 0xFF.toByte()) {
                val bufferedData = receiveBuffer.toByteArray()

                // 如果数据长度为512，则认为是完整数据包
                if (bufferedData.size == 512) {
//                    LogUtils.iTag(
//                        "buffer",
//                        "接收到完整数据包，长度: ${bufferedData.size}"
//                    )
                    // 在这里处理完整的512字节数据
                    onCompleteData?.invoke(bufferedData)
                } else {
                    // 数据长度不是512，判定为数据丢失，记录日志
//                    LogUtils.wTag(
//                        "buffer",
//                        "数据包丢失，期望长度512，实际长度: ${bufferedData.size}，数据已丢弃"
//                    )
                }

                // 清空缓冲池，准备接收下一组数据
                receiveBuffer.reset()
            }
        }
    }

    /**
     * 发送16进制的数组到设备
     * */
    fun sendData(data: ByteArray) {
        LogUtils.eTag("sendData", "准备发送数据")
        BleManager.getInstance().write(
            _connectDevice.value,
            Constant.BLUE_SERVICE_UUID,
            Constant.BLUE_WRITE_UUID,
            data,
            object : BleWriteCallback() {
                override fun onWriteSuccess(current: Int, total: Int, justWrite: ByteArray) {
                    LogUtils.iTag(
                        "write",
                        "${Constant.BLUE_WRITE_UUID} -> 第${current}包数据写成功：" + HexUtil.formatHexString(
                            justWrite
                        )
                    )
                }

                override fun onWriteFailure(e: BleException?) {
                    LogUtils.iTag("write", "写入数据失败：${e}")
                }
            }
        )

    }

    /**
     * 停止扫描
     */
    fun stopScan() {
        BleManager.getInstance().cancelScan()
    }

    /**
     * 断开连接
     */
    fun disconnectDevice(device: BleDevice?) {
        BleManager.getInstance().disconnect(device)
    }

    /**
     * 停止通知
     */
    fun stopNotify(bleDevice: BleDevice) {
        val success = BleManager.getInstance().stopNotify(
            bleDevice,
            Constant.BLUE_SERVICE_UUID,
            Constant.BLUE_READ_UUID
        )
        if (success == true) {
            LogUtils.iTag("notify", "notify取消成功：${Constant.BLUE_READ_UUID}")
        } else {
            LogUtils.iTag("notify", "notify取消失败：${Constant.BLUE_READ_UUID}")
        }
    }

    /**
     * 断开所有设备并清理资源
     */
    fun cleanup() {
        // 清空缓冲池
        receiveBuffer.reset()
        BleManager.getInstance().disconnectAllDevice()
        BleManager.getInstance().destroy()
    }
}